﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ResxCrunch.Utils;
using ResxCrunch.Business.Managers;
using System.Reflection;
using log4net;
using System.IO;

namespace ResxCrunch.Plugins
{
    public class PluginManager : Singleton<PluginManager>
    {
        #region Constants
        /// <summary>
        /// Logger declaration
        /// </summary>
        private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        #endregion Constants

        /// <summary>
        /// Loads all plugins.
        /// </summary>
        /// <param name="pluginsPath">The plugins path.</param>
        /// <returns></returns>
        public List<IResxCrunchPlugin> LoadAllPlugins(string pluginsPath)
        {
            try
            {
                List<string> pluginFilePathList = FileMngr.Instance.GetFileList("*.dll", pluginsPath, true);
                List<IResxCrunchPlugin> pluginList = new List<IResxCrunchPlugin>();

                foreach (string pluginFilePath in pluginFilePathList)
                {
                    IResxCrunchPlugin plugin = this.LoadSinglePlugin(pluginFilePath);

                    if (plugin != null)
                    {
                        pluginList.Add(plugin);
                    }
                }

                return pluginList;
            }
            catch (Exception ex)
            {
                log.Error("Error loading All plugins", ex);
                return new List<IResxCrunchPlugin>();
            }
        }

        /// <summary>
        /// Checks and loads a single plugin.
        /// </summary>
        /// <param name="pluginFilePath">The plugin file path.</param>
        /// <returns>Loaded plugin if the dll implemented the IResxCrunch interface, else null</returns>
        public IResxCrunchPlugin LoadSinglePlugin(string pluginFilePath)
        {
            IResxCrunchPlugin plugin = null;

            try
            {
                Assembly assembly = null;
                assembly = Assembly.LoadFile(Path.GetFullPath(pluginFilePath));

                Type[] types = assembly.GetTypes();
                foreach (Type type in types)
                {
                    if (type.IsAbstract)
                    {
                        ////log.InfoFormat("Assembly '{0}' is abstract", pluginFilePath);
                        continue;
                    }

                    if (type.IsDefined(typeof(ResxCrunchPluginAttribute), true))
                    {
                        plugin = ((IResxCrunchPlugin)Activator.CreateInstance(type));
                        return plugin;
                    }
                }
            }
            catch (Exception ex)
            {
                log.Error("Error while loading plugin", ex);
            }

            return plugin;
        }
    }
}
